package com.dz51.core.basedao.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.Entity;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.type.StandardBasicTypes;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.dz51.core.basedao.base.impl.AbstractBaseDaoImpl;
import com.dz51.core.basedao.dao.IConditionSupport;
import com.dz51.core.basedao.query.IConditionBuilder;
import com.dz51.core.basedao.query.impl.DefaultQueryConditionBuilder;
import com.dz51.core.page.commond.BasePageCommond;
import com.dz51.core.utils.CheckAnnotationUtils;

/**
 * @Title: HibernateSupportDao
 * @Package com.dz51.core.basedao.dao
 * @Description: HibernateAbstract dao层支持
 * @author Zhaoqt
 * @date 2014-5-4 上午5:56:10
 * @version V1.0
 */
public abstract class HibernateAbstractSupportDao<E> extends AbstractBaseDaoImpl<E> implements IConditionSupport {

	@Resource(name = "com.dz51.core.utils.CheckAnnotationUtils")
	protected CheckAnnotationUtils checkAnnotationUtils;

	/**
	 * @Title: addEntity
	 * @Description: 实体储存
	 * @param entity
	 * @throws Exception
	 * @return void
	 */
	public void addEntity(E entity) throws Exception {
		if (entity != null) {
			if (checkAnnotationUtils.checkAnnotation(entity, Entity.class)) {
				this.save(entity);
			} else {
				this.log4jManager.errorCustomLog(entity.getClass().getName(), "checkAnnotation", "该类上方没有定义Entity注解");
			}
		} else {
			this.log4jManager.errorCustomLog(getClass().getName(), "addEntity", "entity is null");
		}
	}

	/**
	 * @Title: batchAddEntities
	 * @Description: 实体批量储存
	 * @param collection
	 * @throws Exception
	 * @return void
	 */
	public void batchAddEntities(Collection<E> collection) throws Exception {
		// collection is not null
		if (collection != null && !collection.isEmpty()) {
			for (E entity : collection) {
				// 校验实体注解是否存在
				if (checkAnnotationUtils.checkAnnotation(entity, Entity.class)) {
					this.save(entity);
				} else {
					this.log4jManager.errorCustomLog(entity.getClass().getName(), "checkAnnotation", "该类上方没有定义Entity注解");
				}
			}
		} else {
			this.log4jManager.errorCustomLog(getClass().getName(), "batchAddEntities", "collection is null");
		}
	}

	/**
	 * @Title: updateEntityByPK
	 * @Description: 主键更新实体
	 * @param entty
	 * @throws Exception
	 * @return void
	 */
	public void updateEntityByPK(E entity) throws Exception {
		if (entity != null) {
			// 校验实体注解是否存在
			if (checkAnnotationUtils.checkAnnotation(entity, Entity.class)) {
				// 批量调用更新清空上次session
				this.clear();
				this.update(entity);
			} else {
				this.log4jManager.errorCustomLog(entity.getClass().getName(), "checkAnnotation", "该类上方没有定义Entity注解");
			}
		} else {
			this.log4jManager.errorCustomLog(getClass().getName(), "updateEntityByPK", "entity is null");
		}
	}

	/**
	 * @Title: deleteEntityByPK
	 * @Description: 主键删除实体
	 * @param entty
	 * @throws Exception
	 * @return void
	 */
	public void deleteEntityByPK(E entity) throws Exception {
		if (entity != null) {
			// 校验实体注解是否存在
			if (checkAnnotationUtils.checkAnnotation(entity, Entity.class)) {
				this.delete(entity);
			} else {
				this.log4jManager.errorCustomLog(entity.getClass().getName(), "checkAnnotation", "该类上方没有定义Entity注解");
			}
		} else {
			this.log4jManager.errorCustomLog(getClass().getName(), "deleteEntityByPK", "entity is null");
		}
	}

	/**
	 * @Title: batchDeleteEntities
	 * @Description: 实体批量删除
	 * @param collection
	 * @throws Exception
	 * @return void
	 */
	public void batchDeleteEntities(Collection<E> collection) throws Exception {
		// collection is not null
		if (collection != null && !collection.isEmpty()) {
			for (E entity : collection) {
				// 校验实体注解是否存在
				if (checkAnnotationUtils.checkAnnotation(entity, Entity.class)) {
					this.delete(entity);
				} else {
					this.log4jManager.errorCustomLog(entity.getClass().getName(), "checkAnnotation", "该类上方没有定义Entity注解");
				}
			}
		} else {
			this.log4jManager.errorCustomLog(getClass().getName(), "batchDeleteEntities", "collection is null");
		}
	}

	/**
	 * @Title: loadEntity
	 * @Description: session.load(..)
	 * @param className
	 * @param id
	 * @throws Exception
	 * @return E
	 */
	public E loadEntity(Class<E> className, Serializable id) throws Exception {
		return this.load(className, id);
	}

	/**
	 * @Title: getEntity
	 * @Description: session.get(..)
	 * @param className
	 * @param id
	 * @return
	 * @throws Exception
	 * @return E
	 * @throws
	 */
	public E getEntity(Class<E> className, Serializable id) throws Exception {
		return this.get(className, id);
	}

	/**
	 * @Title: loadEntity
	 * @Description: session.load(..)
	 * @param id
	 * @throws Exception
	 * @return E
	 */
	@Override
	public Object loadEntity(Serializable id) throws Exception {
		return this.load(entityClass, id);
	}

	/**
	 * @Title: getEntity
	 * @Description: session.get(..)
	 * @param id
	 * @return
	 * @throws Exception
	 * @return E
	 * @throws
	 */
	@Override
	public Object getEntity(Serializable id) throws Exception {
		return this.get(entityClass, id);
	}

	/**
	 * 条件查询db数据. </p> -----------包含sql、hql两种查询语言------------. </p>
	 * -----------paramMap key查询条件匹配符 value查询条件匹配值. </p>
	 * 
	 * @Title: executeFind
	 * @param queryStringType
	 * @param sqlOrHql
	 * @param paramMap
	 * @param start
	 * @param end
	 * @return List<?>
	 * @throws Exception
	 */
	public List<?> executeFind(final QueryStringType queryStringType, final String sqlOrHql, final Map<String, Object> paramMap,
			final int firstResult, final int maxResult) throws Exception {

		this.execute(new HibernateCallback<Object>() {

			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = null;

				if (QueryStringType.HQL.equals(queryStringType)) {
					query = session.createQuery(sqlOrHql);
				} else if (QueryStringType.SQL.equals(queryStringType)) {
					query = session.createSQLQuery(sqlOrHql);
				} else {
					query = session.createQuery(sqlOrHql);
				}
				if ((paramMap != null) && (paramMap.size() > 0)) {
					query.setProperties(paramMap);
				}

				if (firstResult > 0) {
					query.setFirstResult(firstResult);
				}
				if (maxResult > 0) {
					query.setMaxResults(maxResult);
				}
				return query.list();
			}
		});
		this.log4jManager.errorCustomLog(getClass().getName(), "executeFind", "find Invalid");
		return null;
	}

	/**
	 * count 查询 </p> -----------包含sql、hql两种查询语言------------. </p>
	 * -----------paramMap key查询条件匹配符 value查询条件匹配
	 * 
	 * @Title: count
	 * @param queryStringType
	 * @param sqlOrHql
	 * @param paramMap
	 * @return
	 * @throws ExceptionLong
	 */
	public Long count(final QueryStringType queryStringType, final String sqlOrHql, final Map<String, Object> paramMap) throws Exception {
		this.execute(new HibernateCallback<Long>() {
			public Long doInHibernate(Session session) throws HibernateException, SQLException {

				int startIndex = -1;
				String countHQL = "";

				if ((startIndex = sqlOrHql.indexOf(" ORDER BY ")) != -1) {
					countHQL = countHQL.substring(0, startIndex);
				}
				Query query = null;
				if (QueryStringType.SQL.equals(queryStringType)) {
					query = session.createSQLQuery("SELECT COUNT(*) as count " + countHQL).addScalar("count", StandardBasicTypes.LONG);
				} else {
					query = session.createQuery("SELECT COUNT(*) " + countHQL);
				}
				if (paramMap != null && paramMap.size() > 0) {
					query.setProperties(paramMap);
				}
				return (Long) query.list().iterator().next();
			}
		});
		this.log4jManager.errorCustomLog(getClass().getName(), "count", "find Invalid");
		return null;
	}

	/**
	 * {@link com.dz51.core.basedao.query.IConditionBuilder}
	 * 
	 * @Title: find
	 * @param conditionBuilder
	 * @return
	 * @throws Exception
	 */
	@Override
	public BasePageCommond find(IConditionBuilder conditionBuilder) throws Exception {
		BasePageCommond basePageCommond = new BasePageCommond();
		DefaultQueryConditionBuilder defaultQueryConditionBuilder = (DefaultQueryConditionBuilder) conditionBuilder;
		boolean isCriteria = defaultQueryConditionBuilder.isCriteria();
		// -------------------- 启用 Criteria查询 start
		// --------------------------------------//
		if (isCriteria) {
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(entityClass);
			Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
			defaultQueryConditionBuilder.setCriteria(criteria);
			// 关键词 属性查询 方法内部验证。关键字为空则不执行
			defaultQueryConditionBuilder.addCriteriaKeyword();
			// 属性集查询 方法内部验证。map为空则不执行
			defaultQueryConditionBuilder.addCriteriaMap();
			// 查询数据最大数量
			Object obj = criteria.setProjection(Projections.rowCount()).uniqueResult();
			Integer totalCount = new Integer("0");
			if (obj instanceof Long) {
				totalCount = ((Long) obj).intValue();
			} else if (obj instanceof Integer) {
				totalCount = (Integer) obj;
			}
			criteria.setProjection(null);
			// 分页计算查询
			defaultQueryConditionBuilder.addCriteriaPager();
			// 排序
			defaultQueryConditionBuilder.addCriteriaOrder();

			basePageCommond.setPageCount(totalCount);
			basePageCommond.setResultCollection(criteria.list());
		}
		// -------------------- 启用 Criteria查询 end
		// --------------------------------------//

		return basePageCommond;
	}

}
